package gbench.sandbox.matlib;

import org.junit.jupiter.api.Test;

import gbench.common.fs.XlsFile.DataMatrix;
import gbench.common.matlib.MatlibCanvas.NVec;
import gbench.common.matlib.MatlibCanvas.Range;
import gbench.common.matlib.MatlibCanvas.XVec;
import gbench.common.tree.LittleTree.IRecord;

import static gbench.common.matlib.MatlibCanvas.Range.rG;
import static gbench.common.matlib.data.Pipe.CAST;
import static gbench.common.matlib.data.Pipe.DUMMY;
import static gbench.common.matlib.data.Pipe.NULL;
import static gbench.common.matlib.data.Pipe.PIPE;
import static gbench.common.tree.LittleTree.IRecord.aaclc;

/**
 * 计算管道的演示
 * @author Administrator
 *
 */
public class JunitPipe {
    
    /**
     * 使用管道来序列化操作。
     */
    @Test
    public void foo() {
        final var dframe = PIPE(100)
           .bind(Range::of) // 生成一个 [0,100)的序列 即  [0,1,...,99] 的数据范围。 
           .bind(NVec::of) // 把 [0,1,...,99] 转换成 NVec
           .bind(nvec->nvec.sliceS(e -> e, 10) // 按照10x10的形状分解
                .collect(aaclc(IRecord::A2REC))) // 按照10x10的形状分解，并构造dframe
           .evaluate(); // 取得dframe
        System.out.println("dframe(列顺序):\n"+dframe.toString2());
        
        final var xvec = PIPE(Double.class)
           .bind(dframe::toArray2) // 把 dframe 转换成 二维数组
           .bind(DataMatrix::simpleOf) // 把二维数组 转换成  数据矩阵 
           .bind(DataMatrix::getCells) // 提取数据矩阵的 二维数组
           //.bind(DataMatrix::transpose) // 变换行列顺序
           .bind(XVec::OF) // 把 二维数组转换成  XVec,XVec的元素为 Double[]
           .bind(e->e.fmap(NVec::new)) // 把 xvec的Double[]元素转换成 NVec类型的结构。
           .evaluate();
        System.out.println("xvec:"+xvec);
    }
    
    /**
     * 把管道作为函数定义来使用：管道可以被视作一个类型化的 lambda 函数
     */
    @Test
    public void lambda_pipe() {
        final var lambda = PIPE(NULL(Object[].class)).bind(CAST(Double[][].class)).bind(XVec::OF).bind(v->v.fmap(NVec::new));// 使用管道定义函数 lambda
        final var xvec = rG(1, 100).mutate(NVec::new).reshape(lambda::evaluate,10,10); // 使用管道函数 
        System.out.println(xvec);
    }
    
    /**
     * 把管道作为函数定义来使用：管道可以被视作一个类型化的 lambda 函数
     * 使用dummy来演示
     */
    @Test
    public void lambda_pipe2() {
        final var lambda = DUMMY(Object[].class).cast(Double[][].class).bind(XVec::OF).bind(v->v.fmap(NVec::new));// 使用管道定义函数 lambda
        final var xvec = rG(1, 100).mutate(NVec::new).reshape(lambda::evaluate,10,10); // 使用管道函数 
        System.out.println(xvec);
    }
    
}
